<template>
  <div ref="containerRef" class="dynamic-buttons-container">
    <template v-for="(button, index) in state.visibleButtons">
      <a-button
        v-if="!button.icon"
        :key="index"
        :disabled="button.disabledHandler ? button.disabledHandler(props.data, props.dataIndex) : false"
        v-bind="button.otherProps ? button.otherProps(props.data, props.dataIndex) : {}"
        type="link"
        @click="button.handler(props.data, props.dataIndex)"
      >
        {{ getlabel(button.label) }}
      </a-button>
      <a-tooltip v-else :key="'icon' + index" :title="getlabel(button.label)">
        <span
          :class="{
            'disabled-tag-a': button.disabledHandler ? button.disabledHandler(props.data, props.dataIndex) : false
          }"
        >
          <i
            class="icpIconfont"
            :class="button.class + ' ' + getlabel(button.icon)"
            @click="button.handler(props.data, props.dataIndex)"
          ></i>
        </span>
      </a-tooltip>
    </template>
    <a-dropdown v-if="state.hiddenButtons.length > 0">
      <a-button type="link"> <i class="icpIconfont gengduocaozuo"></i> </a-button>
      <template #overlay>
        <a-menu>
          <template v-for="(button, index) in state.hiddenButtons">
            <a-menu-item
              v-if="button.visibleHandler ? button.visibleHandler(props.data, index) : true"
              :key="index"
              :disabled="button.disabledHandler ? button.disabledHandler(props.data, index) : false"
              @click="button.handler(props.data, props.dataIndex)"
            >
              {{ getlabel(button.label) }}
            </a-menu-item>
          </template>
        </a-menu>
      </template>
    </a-dropdown>
  </div>
</template>

<script lang="ts" setup>
import { ref, reactive, onMounted, onBeforeUnmount, computed } from 'vue'

interface Button {
  label: string | ((row: any) => string)
  otherProps?: any
  icon?: string | ((row: any) => string)
  class?: string
  visibleHandler?: (row: any, index?: number) => boolean
  disabledHandler?: (row: any, index?: number) => boolean
  handler: (row: any, index?: number) => void
}

const props = defineProps<{
  data: any
  dataIndex?: number
  buttonList: Button[]
}>()

const containerRef = ref()
const state = reactive<{
  visibleButtons: Button[]
  hiddenButtons: Button[]
}>({
  visibleButtons: [],
  hiddenButtons: []
})

const buttons = computed(() => {
  return props.buttonList.filter((button) =>
    button.visibleHandler ? button.visibleHandler(props.data, props.dataIndex) : true
  )
})

const handleResize = () => {
  const containerWidth = containerRef.value?.clientWidth
  const buttonWidths = buttons.value.map((button) => estimateButtonWidth(button))
  let totalWidth = 0
  let maxVisibleButtons = 0

  // 动态调整可见按钮数量，确保不超过容器宽度
  for (let i = 0; i < buttonWidths.length; i++) {
    totalWidth += buttonWidths[i]
    if (totalWidth + (i === buttonWidths.length - 1 ? 0 : 30) <= containerWidth) {
      // 隐藏按钮数大于0，需要判断容器剩余空间是否能够显示所有按钮的宽度加上更多按钮的宽度（30px）
      maxVisibleButtons = i + 1
    } else {
      break
    }
  }

  // 如果剩余空间足够，并且隐藏按钮中只有一个按钮，将其显示在可见按钮中
  if (
    maxVisibleButtons < buttons.value.length &&
    state.hiddenButtons.length === 1 &&
    totalWidth - 8 <= containerWidth
  ) {
    maxVisibleButtons += 1
  }

  // 更新可见和隐藏按钮数组
  state.visibleButtons = buttons.value.slice(0, maxVisibleButtons)
  state.hiddenButtons = buttons.value.slice(maxVisibleButtons)
}

const estimateButtonWidth = (button) => {
  // 宽度估算
  return button.icon ? 16 + 8 : getlabel(button.label).length * 14 + 20 // 根据设计调整乘数和常数
}

const getlabel = (label) => {
  if (typeof label === 'function') {
    return label(props.data)
  }
  return label
}

let resizeObserver
onMounted(() => {
  handleResize()
  resizeObserver = new ResizeObserver(handleResize)
  resizeObserver.observe(containerRef.value)
})

onBeforeUnmount(() => {
  resizeObserver?.unobserve(containerRef.value)
})
</script>

<style lang="less" scoped>
.dynamic-buttons-container {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;

  .disabled-tag-a {
    cursor: not-allowed;
    .icpIconfont {
      pointer-events: none;
      opacity: 0.7;
    }
  }
}
</style>
